#include <stdint.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <pthread.h>
#include <hiredis/hiredis.h>
#include "idc_ubus_lora.h"
#include "idc_ubus_common.h"
#include "crc.h"
#include "frame_util.h"
#include "lora_service.h"
#include "data_type.h"
#include <semaphore.h>

extern pShartData ubus_cmd_Psd;

/**
 * 获取电源系统充放电信息
 */ 
int query_lora_ver(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg)
{
        //lora_printf("AT+VER?\r\n");
        uint8_t output[11];
        uint16_t len = protocol_encode(0xA5, 0x69, NULL, 0, output);
        lora_send(output, len);
        return 0;
} 
int query_lora_reboot(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg){
        //lora_printf("AT+REBOOT\r\n");
        uint8_t output[11];
        uint16_t len = protocol_encode(0xA5, 0x68, NULL, 0, output);
        lora_send(output, len);
        return 0;
}
int query_lora_esn(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg){
        lora_printf("AT+ESN?\r\n");
        return 0;
}
int lora_in_at(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg){
        uint8_t output[11];
        uint16_t len = protocol_encode(0xA5, 0x60, (uint8_t[]){0x01}, 1, output);
        lora_send(output, len);
        return 0;
}
int lora_exit_at(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg){
        uint8_t output[11];
        uint16_t len = protocol_encode(0xA5, 0x60, (uint8_t[]){0x00}, 1, output);
        lora_send(output, len);
        return 0;
}
int lora_reset(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg){
        //lora_printf("AT+RESET\r\n");
        uint8_t output[11];
        uint16_t len = protocol_encode(0xA5, 0x61, NULL, 0, output);
        lora_send(output, len);
        return 0;
}
int query_lora_addr(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg){
        uint8_t output[11];
        uint16_t len = protocol_encode(0xA5, 0x62, NULL, 0, output);
        lora_send(output, len);

        struct timespec ts;
        // 获取当前时钟（通常使用CLOCK_REALTIME），作为计算超时时间的基准
        if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
                perror("clock_gettime failed");
                //sem_destroy(&ubus_cmd_Psd.sem);
                return 1;
        }
        ts.tv_sec += 3; // 设置超时时间为当前时间后的5秒

        int ret = sem_timedwait(&ubus_cmd_Psd.sem, &ts);
        //sem_wait(&ubus_cmd_Psd.sem);
        blob_buf_init(&b, 0);
        if (ret == 0) {
                pthread_mutex_lock(&ubus_cmd_Psd.mutex); // 加锁
                blobmsg_add_u32(&b, "is_center", ubus_cmd_Psd.data[0]);
                blobmsg_add_u32(&b, "addr", (((ubus_cmd_Psd.data[1]<<8) & 0xFF00) | (ubus_cmd_Psd.data[2] & 0xFF)));
                blobmsg_add_u32(&b, "group_addr", (((ubus_cmd_Psd.data[3]<<8) & 0xFF00) | (ubus_cmd_Psd.data[4])));
                ubus_send_reply(ctx, req, b.head);
                pthread_mutex_unlock(&ubus_cmd_Psd.mutex); // 解锁
        }else{
                ubus_send_reply(ctx, req, b.head);
        }
        return 0;
}
int set_lora_addr(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg){
        struct blob_attr *tb[2];
        blobmsg_parse(lora_set_addr_policy, 2, tb, blob_data(msg), blob_len(msg));
        if (tb[0] && tb[1]) {
                const char *addr = blobmsg_get_string(tb[0]);
                const char *group_addr = blobmsg_get_string(tb[1]);
                uint8_t data[4];
                uint16_t hex_addr, hex_group_addr;

                if (sscanf(addr, "%hX", &hex_addr) == 1) {
                        data[0] = (hex_addr) >> 8 & 0xFF;
                        data[1] = hex_addr & 0xFF;
                } else {
                        printf("addr 转换失败\n");
                        return 0;
                }
                if (sscanf(group_addr, "%hX", &hex_group_addr) == 1) {
                        data[2] = (hex_group_addr >> 8) & 0xFF;
                        data[3] = hex_group_addr & 0xFF;
                } else {
                        printf("group_addr 转换失败\n");
                        return 0;
                }
                uint8_t output[11];
                uint16_t len = protocol_encode(0xA5, 0x63, data, 4, output);
                lora_send(output, len);
        }
        return 0;
}
int query_lora_cell(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg){
        //lora_printf("AT+CELL?\r\n");
        uint8_t output[11];
        uint16_t len = protocol_encode(0xA5, 0x66, NULL, 0, output);
        lora_send(output, len);

        struct timespec ts;
        // 获取当前时钟（通常使用CLOCK_REALTIME），作为计算超时时间的基准
        if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
                perror("clock_gettime failed");
                //sem_destroy(&ubus_cmd_Psd.sem);
                return 1;
        }
        ts.tv_sec += 3; // 设置超时时间为当前时间后的5秒

        int ret = sem_timedwait(&ubus_cmd_Psd.sem, &ts);
        //sem_wait(&ubus_cmd_Psd.sem);
        blob_buf_init(&b, 0);
        if (ret == 0) {
                pthread_mutex_lock(&ubus_cmd_Psd.mutex); // 加锁
                blobmsg_add_u32(&b, "cell",  ubus_cmd_Psd.data[0]);
                ubus_send_reply(ctx, req, b.head);
                pthread_mutex_unlock(&ubus_cmd_Psd.mutex); // 解锁
        }else{
                ubus_send_reply(ctx, req, b.head);
        }
        return 0;
}
int set_lora_cell(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg){
        struct blob_attr *tb[1];
        blobmsg_parse(lora_set_cell_policy, 1, tb, blob_data(msg), blob_len(msg));
        if (tb[0]) {
                int id = blobmsg_get_u32(tb[0]);

                uint8_t output[11];
                uint16_t len = protocol_encode(0xA5, 0x67, (uint8_t[]){id&0xFF}, 1, output);
                lora_send(output, len);
                // printf("AT+CELL=%d\r\n", id);
                // lora_printf("AT+CELL=%d\r\n", id);
        }
        return 0;
}
int query_lora_pwr(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg){
        uint8_t output[7];
        uint16_t len = protocol_encode(0xA5, 0x70, NULL, 0, output);
        lora_send(output, len);
        struct timespec ts;
        // 获取当前时钟（通常使用CLOCK_REALTIME），作为计算超时时间的基准
        if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
                perror("clock_gettime failed");
                //sem_destroy(&ubus_cmd_Psd.sem);
                return 1;
        }
        ts.tv_sec += 3; // 设置超时时间为当前时间后的5秒

        int ret = sem_timedwait(&ubus_cmd_Psd.sem, &ts);
        blob_buf_init(&b, 0);
        if (ret == 0) {
                pthread_mutex_lock(&ubus_cmd_Psd.mutex); // 加锁
                blobmsg_add_u32(&b, "pwr", ubus_cmd_Psd.data[0]);
                ubus_send_reply(ctx, req, b.head);
                pthread_mutex_unlock(&ubus_cmd_Psd.mutex); // 解锁
        }else{
                ubus_send_reply(ctx, req, b.head);
        }
        return 0;
}
int set_lora_pwr(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg){
        struct blob_attr *tb[1];
        blobmsg_parse(lora_set_pwr_policy, 1, tb, blob_data(msg), blob_len(msg));
        if (tb[0]) {
                char pwr = blobmsg_get_u32(tb[0]);

                char data[] = {pwr};

                uint8_t output[11];
                uint16_t len = protocol_encode(0xA5, 0x6F, data, 1, output);
                lora_send(output, len);
        }
        return 0;
}
int query_lora_wor(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg){
        lora_printf("AT+WOR?\r\n");
        return 0;
}
int set_lora_wor(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg){
        struct blob_attr *tb[1];
        blobmsg_parse(lora_set_wor_policy, 1, tb, blob_data(msg), blob_len(msg));
        if (tb[0]) {
                //唤醒周期，可选值100/200/300/500/1000/2000/3000 单位 ms
                int wor = blobmsg_get_u32(tb[0]);
                printf("AT+WOR=%d\r\n", wor);
                lora_printf("AT+WOR=%d\r\n", wor);
        }
        return 0;
}
int query_lora_bps(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg){
        uint8_t output[7];
        uint16_t len = protocol_encode(0xA5, 0x6E, NULL, 0, output);
        lora_send(output, len);
        struct timespec ts;
        // 获取当前时钟（通常使用CLOCK_REALTIME），作为计算超时时间的基准
        if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
                perror("clock_gettime failed");
                //sem_destroy(&ubus_cmd_Psd.sem);
                return 1;
        }
        ts.tv_sec += 3; // 设置超时时间为当前时间后的5秒

        int ret = sem_timedwait(&ubus_cmd_Psd.sem, &ts);
        blob_buf_init(&b, 0);
        if (ret == 0) {
                pthread_mutex_lock(&ubus_cmd_Psd.mutex); // 加锁
                printf("bps data:");
                for (size_t i = 0; i < 6; i++)
                {
                       printf("%02X ", ubus_cmd_Psd.data[i]);
                }
                printf("\n");
                uint32_t ctrl_bps = ((ubus_cmd_Psd.data[0]<<16) & 0xFF0000) | ((ubus_cmd_Psd.data[1]<<8) & 0xFF00) | (ubus_cmd_Psd.data[2] & 0xFF);
                uint32_t data_bps = ((ubus_cmd_Psd.data[3]<<16) & 0xFF0000) | ((ubus_cmd_Psd.data[4]<<8) & 0xFF00) | (ubus_cmd_Psd.data[5] & 0xFF);
                printf("ctrl_bps:%d, data_bps: %d\n", ctrl_bps, data_bps);
                blobmsg_add_u32(&b, "ctrl_bps", ctrl_bps);
                blobmsg_add_u32(&b, "data_bps", data_bps);
                ubus_send_reply(ctx, req, b.head);
                pthread_mutex_unlock(&ubus_cmd_Psd.mutex); // 解锁
        }else{
                ubus_send_reply(ctx, req, b.head);
        }
        return 0;
}
int set_lora_bps(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg){
        struct blob_attr *tb[2];
        blobmsg_parse(lora_set_bps_policy, 2, tb, blob_data(msg), blob_len(msg));
        if (tb[0] && tb[1]) {
                uint32_t type = blobmsg_get_u32(tb[0]);
                uint32_t bps = blobmsg_get_u32(tb[1]);

                uint8_t data[4];
                data[0] = type & 0xFF;
                data[1] = ((bps >> 16) & 0xFF);
                data[2] = ((bps >> 8) & 0xFF);
                data[3] = (bps& 0xFF);

                uint8_t output[11];
                uint16_t len = protocol_encode(0xA5, 0x6D, data, 4, output);
                lora_send(output, len);
        }
        return 0;
}
int query_lora_lp(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg){
        //lora_printf("AT+LP?\r\n");
        uint8_t output[11];
        uint16_t len = protocol_encode(0xA5, 0x6C, NULL, 0, output);
        lora_send(output, len);
        struct timespec ts;
        // 获取当前时钟（通常使用CLOCK_REALTIME），作为计算超时时间的基准
        if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
                perror("clock_gettime failed");
                //sem_destroy(&ubus_cmd_Psd.sem);
                return 1;
        }
        ts.tv_sec += 3; // 设置超时时间为当前时间后的5秒

        int ret = sem_timedwait(&ubus_cmd_Psd.sem, &ts);
        blob_buf_init(&b, 0);
        if (ret == 0) {
                pthread_mutex_lock(&ubus_cmd_Psd.mutex); // 加锁
                blobmsg_add_u32(&b, "lp", ubus_cmd_Psd.data[0]);
                ubus_send_reply(ctx, req, b.head);
                pthread_mutex_unlock(&ubus_cmd_Psd.mutex); // 解锁
        }else{
                ubus_send_reply(ctx, req, b.head);
        }
        return 0;
}
int set_lora_lp(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg){
        struct blob_attr *tb[1];
        blobmsg_parse(lora_set_lp_policy, 1, tb, blob_data(msg), blob_len(msg));
        if (tb[0]) {      
                //0 表示 Type A;1 表示 Type B;2 表示 TYPE C；3 表示TYPE D
                int lp = blobmsg_get_u32(tb[0]); 
                // printf("AT+LP=%d\r\n", lp);
                // lora_printf("AT+LP=%d\r\n", lp);

                uint8_t output[11];
                uint16_t len = protocol_encode(0xA5, 0x6B, (uint8_t[]){lp&0xFF}, 1, output);
                lora_send(output, len);
        }
        return 0;
}
int query_lora_awake(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg){
        lora_printf("AT+AWAKE?\r\n");
        return 0;
}
int set_lora_awake(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg){
        struct blob_attr *tb[1];
        blobmsg_parse(lora_set_awake_policy, 1, tb, blob_data(msg), blob_len(msg));
        if (tb[0]) {
                //2 持续监听时间；单位 ms
                int awake = blobmsg_get_u32(tb[0]); 
                printf("AT+AWAKE=%d\r\n", awake);
                lora_printf("AT+AWAKE=%d\r\n", awake);
        }
        return 0;
}
int query_lora_trans(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg){
        //lora_printf("AT+TRANS?\r\n");
        uint8_t output[7];
        uint16_t len = protocol_encode(0xA5, 0x64, NULL, 0, output);
        lora_send(output, len);
        struct timespec ts;
        // 获取当前时钟（通常使用CLOCK_REALTIME），作为计算超时时间的基准
        if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
                perror("clock_gettime failed");
                //sem_destroy(&ubus_cmd_Psd.sem);
                return 1;
        }
        ts.tv_sec += 3; // 设置超时时间为当前时间后的5秒

        int ret = sem_timedwait(&ubus_cmd_Psd.sem, &ts);
        blob_buf_init(&b, 0);
        if (ret == 0) {
                pthread_mutex_lock(&ubus_cmd_Psd.mutex); // 加锁
                blobmsg_add_u32(&b, "trans_mode", ubus_cmd_Psd.data[1]);
                blobmsg_add_u32(&b, "trans_addr", (ubus_cmd_Psd.data[2]<<8 | ubus_cmd_Psd.data[3]));
                ubus_send_reply(ctx, req, b.head);
                pthread_mutex_unlock(&ubus_cmd_Psd.mutex); // 解锁
        }else{
                ubus_send_reply(ctx, req, b.head);
        }
        return 0;
}
int set_lora_trans(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg){
        struct blob_attr *tb[3];
        blobmsg_parse(lora_set_trans_policy, 3, tb, blob_data(msg), blob_len(msg));
        if (tb[0] && tb[1] && tb[2]) {
                const int mode = blobmsg_get_u32(tb[0]);
                const char *addr = blobmsg_get_string(tb[1]);
                const int type = blobmsg_get_u32(tb[2]);

                //printf("AT+TRANS=%d,%s,%d\r\n", mode, addr, type);
                //lora_printf("AT+TRANS=%d,%s,%d\r\n", mode, addr, type);
                uint16_t hex_addr;
                uint8_t data[4];
                data[0] = mode & 0xFF;
                data[3] = type & 0xFF;
                if (sscanf(addr, "%hX", &hex_addr) == 1) {
                        data[1] = (hex_addr >> 8) & 0xFF;
                        data[2] = hex_addr & 0xFF;
                } else {
                        printf("addr 转换失败\n");
                        return 0;
                }
                uint8_t output[11];
                uint16_t len = protocol_encode(0xA5, 0x65, data, 4, output);
                lora_send(output, len);
        }
        return 0;
}

int at_send_data(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg){
        struct blob_attr *tb[2];
        blobmsg_parse(lora_at_send_policy, 2, tb, blob_data(msg), blob_len(msg));
        if (tb[0] && tb[1]) {
                const char *addr = blobmsg_get_string(tb[0]);
                const char *data = blobmsg_get_string(tb[1]);
                
                printf("AT+SEND=%s,%d,%s,0\r\n", addr, strlen(data), data);
                lora_printf("AT+SEND=%s,%d,%s,0\r\n", addr, strlen(data), data);
        }
        return 0;
}

int trans_send_data(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg){
        struct blob_attr *tb[1];
        blobmsg_parse(lora_trans_send_policy, 1, tb, blob_data(msg), blob_len(msg));
        if (tb[0]) {
                const char *data = blobmsg_get_string(tb[0]);
                printf("%s\r\n", data);
                lora_printf("%s\r\n", data);
        }
        return 0;
}